using System;
using System.Collections.Generic;
using System.ComponentModel;

using CureConsulting;
using CureConsulting.Business;

using Bug.Net.Common.DataObjects;

namespace Bug.Net.Business.BusinessObjects
{
	/// <summary>
	/// Business Object for login.
	/// </summary>
	public partial class LoginBO : BusinessObjectBase
	{
		#region Constructors

		/// <summary>
		/// Create a LoginBO object
		/// </summary>
		public LoginBO()
		{
			this.login = new Login();
		}

		/// <summary>
		/// Create a LoginBO object
		/// </summary>
		public LoginBO(int id) : this()
		{
			this.login.Id = id;
		}
		
		/// <summary>
		/// Create a LoginBO object
		/// </summary>
		/// <param name="active"></param>
		/// <param name="email"></param>
		/// <param name="firstName"></param>
		/// <param name="lastName"></param>
		/// <param name="userName"></param>
		/// <param name="password"></param>
		/// <param name="salt"></param>
		/// <param name="passwordQuestion"></param>
		/// <param name="passwordAnswer"></param>
		/// <param name="createDate"></param>
		public LoginBO( bool active, string email, string firstName, string lastName, string userName, string password, string salt, string passwordQuestion, string passwordAnswer, DateTime createDate ) : this()
		{
			this.login.Active = active;
			this.login.Email = email;
			this.login.FirstName = firstName;
			this.login.LastName = lastName;
			this.login.UserName = userName;
			this.login.Password = password;
			this.login.Salt = salt;
			this.login.PasswordQuestion = passwordQuestion;
			this.login.PasswordAnswer = passwordAnswer;
			this.login.CreateDate = createDate;
		}

		/// <summary>
		/// Create a LoginBO object
		/// </summary>
		/// <param name="Login"></param>
		public LoginBO(Login login)
		{
			if(login != null)
			{
				this.login = login;
			}
			else
			{
				throw new ArgumentNullException();
			}
		}
		
		#endregion
		
		#region Member Variables
		
		private Login login;
		
		protected SortableBindingList<RoleBO> _roles;
		
		#endregion
		
		#region Private Methods
		
		void _roles_ListChanged(object sender, ListChangedEventArgs e)
        {
            switch (e.ListChangedType)
            {
                case ListChangedType.ItemAdded:
                    if (_roles[e.NewIndex] != null)
                    {
                        POCO.Roles.Insert(e.NewIndex, _roles[e.NewIndex].POCO);
                    }
                    break;

                case ListChangedType.ItemDeleted:
					POCO.Roles.RemoveAt(e.NewIndex);
                    break;
					
				case ListChangedType.Reset:
                    POCO.Roles.Clear();
                    break;

                default:
                    break;
			}
        }
		
		
		#endregion
		
		#region Public Properties
		
		/// <summary>
        /// Property for POCO
        /// </summary>
        public Login POCO
        {
            get { return login; }
        }
		
		/// <summary>
        /// Property for Id
        /// </summary>
        public override int? Id
        {
            get { return login.Id; }
			set
			{
				if(value.HasValue)
					login.Id = value;
			}
        }
		
		/// <summary>
		/// Login Active
		/// </summary>
		public virtual bool Active
		{
			get { return login.Active; }
			set
			{
				login.Active = value;
				NotifyPropertyChanged("Active");
			}
		}

		/// <summary>
		/// Login Email
		/// </summary>
		public virtual string Email
		{
			get { return login.Email; }
			set
			{				
				login.Email = (value != null && value.Length > 0) ? value : null;
				NotifyPropertyChanged("Email");
			}
		}

		/// <summary>
		/// Login FirstName
		/// </summary>
		public virtual string FirstName
		{
			get { return login.FirstName; }
			set
			{				
				login.FirstName = (value != null && value.Length > 0) ? value : null;
				NotifyPropertyChanged("FirstName");
			}
		}

		/// <summary>
		/// Login LastName
		/// </summary>
		public virtual string LastName
		{
			get { return login.LastName; }
			set
			{				
				login.LastName = (value != null && value.Length > 0) ? value : null;
				NotifyPropertyChanged("LastName");
			}
		}

		/// <summary>
		/// Login UserName
		/// </summary>
		public virtual string UserName
		{
			get { return login.UserName; }
			set
			{
				login.UserName = value;
				NotifyPropertyChanged("UserName");
			}
		}

		/// <summary>
		/// Login Password
		/// </summary>
		public virtual string Password
		{
			get { return login.Password; }
			set
			{
				login.Password = value;
				NotifyPropertyChanged("Password");
			}
		}

		/// <summary>
		/// Login Salt
		/// </summary>
		public virtual string Salt
		{
			get { return login.Salt; }
			set
			{
				login.Salt = value;
				NotifyPropertyChanged("Salt");
			}
		}

		/// <summary>
		/// Login PasswordQuestion
		/// </summary>
		public virtual string PasswordQuestion
		{
			get { return login.PasswordQuestion; }
			set
			{				
				login.PasswordQuestion = (value != null && value.Length > 0) ? value : null;
				NotifyPropertyChanged("PasswordQuestion");
			}
		}

		/// <summary>
		/// Login PasswordAnswer
		/// </summary>
		public virtual string PasswordAnswer
		{
			get { return login.PasswordAnswer; }
			set
			{				
				login.PasswordAnswer = (value != null && value.Length > 0) ? value : null;
				NotifyPropertyChanged("PasswordAnswer");
			}
		}

		/// <summary>
		/// Login CreateDate
		/// </summary>
		public virtual DateTime CreateDate
		{
			get { return ConvertDateTimeFromDB(login.CreateDate); }
			set
			{
				login.CreateDate = ConvertDateTimeToDB(value);
				NotifyPropertyChanged("CreateDate");
			}
		}

		/// <summary>
		/// Login Roles
		/// </summary>
		[ManyToMany]
		public virtual SortableBindingList<RoleBO> Roles
		{
			get
			{
				if(_roles == null)
				{			
					SortableBindingList<RoleBO> retVal = new SortableBindingList<RoleBO>();

					if (login.Roles != null)
					{
						foreach (Role tempRole in login.Roles)
						{
							retVal.Add(new RoleBO(tempRole));
						}
					}
		
					_roles = retVal;
					_roles.ListChanged += new ListChangedEventHandler(_roles_ListChanged);
				}
				
				return _roles;
			}
		}

		
		/// <summary>
        /// Property for Dirty
        /// </summary>
        public override bool Dirty
        {
            get { return login.Dirty; }
        }
		
		/// <summary>
        /// Property for IsNew
        /// </summary>
        public override bool IsNew
        {
            get { return login.IsNew; }
        }
		
		#endregion
		
		#region Public Methods
		
		/// <summary>
		/// Update a LoginBO object
		/// </summary>
		public void UpdateBO(Login login)
		{
			this.login.Id = login.Id;
			this.login.Active = login.Active;
			this.login.Email = login.Email;
			this.login.FirstName = login.FirstName;
			this.login.LastName = login.LastName;
			this.login.UserName = login.UserName;
			this.login.Password = login.Password;
			this.login.Salt = login.Salt;
			this.login.PasswordQuestion = login.PasswordQuestion;
			this.login.PasswordAnswer = login.PasswordAnswer;
			this.login.CreateDate = login.CreateDate;
		}
		
		/// <summary>
		/// Override Equals to compare object properties.
		/// Note that child collections are ignored to avoid performance issues
		/// and possible circular references. Any DateTime properties will be considered equal
		/// if they differ by less than a second.  This is necessary because the RDBMS datetime data type
		/// (on Oracle or Sql Server) has less precision than the .Net DateTime struct.
		/// </summary>
		/// <param name="obj"></param>
		/// <returns></returns>
		public override bool Equals(object obj)
		{
			if(obj == null || obj.GetType() != this.GetType()) { return false; }
			
			if(Object.ReferenceEquals(this, obj)) { return true; }
			
			LoginBO other = (LoginBO)obj;

			return
			(
				this.Id == other.Id
				&& this.Active == other.Active
				&& this.Email == other.Email
				&& this.FirstName == other.FirstName
				&& this.LastName == other.LastName
				&& this.UserName == other.UserName
				&& this.Password == other.Password
				&& this.Salt == other.Salt
				&& this.PasswordQuestion == other.PasswordQuestion
				&& this.PasswordAnswer == other.PasswordAnswer
				&& this.CreateDate.Subtract(other.CreateDate).Duration().Ticks < TimeSpan.TicksPerSecond
			);
			
		}
		
		/// <summary>
		/// This class is mutable and therefore should not be used as a Hashtable key.
		/// GetHashCode will return the same value for all instances of this class.
		/// </summary>
		/// <returns></returns>
		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		/// <summary>
		/// Reset the dirty flag
		/// </summary>
		public override void ResetDirty()
		{
			login.ResetDirty();
		}
		
		#endregion
	}
}